package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JTextField;

import model.Account;
import model.Database;
import model.Encryption;
import model.IOFile;
import model.OptionMessenger;
import model.SystemTableModel;
import model.UICommand;
import ui.BusyDialog;
import view.MainFrame;
import view.SystemPanel;

public class SystemController implements ActionListener, MouseListener,
		FocusListener, KeyListener {
	private SystemPanel view;
	private Connection connect;
	private PreparedStatement preStm;
	private SystemTableModel tableModel;
	private JCheckBox checkBox;

	public SystemController(SystemTableModel tableModel) {
		this.tableModel = tableModel;
		this.view = new SystemPanel(tableModel, this);
	}

	// TODO action event
	@Override
	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		switch (cmd) {
		case UICommand.SHOW_CMD:// show panel add account
			if (!isUser())
				view.showAddPanel();
			break;
		case UICommand.ADD_CMD:// query add new account
			addAccount();
			break;
		case UICommand.MODIFY_CMD:// used by notify menu
			if (isValid())
				if (view.getSelectedRealRow() != -1)
					view.showModifyPanel();
				else
					OptionMessenger.showMessageDialog(view,
							"Chọn tài khoản cần sửa", "Thông báo",
							OptionMessenger.QUESTION_MESSAGE);
			break;
		case UICommand.DELETE_CMD:// used by delete menu
			if (view.getSelectedRealRow() != -1) {
				if (view.checkUserName("admin", "guess")) {
					OptionMessenger.showMessageDialog(view,
							"Đây là tài khoản hệ thống không thể bị xóa",
							"Cảnh báo", OptionMessenger.WARNING_MESSAGE);
					return;
				} else {
					if (isValid())
						if (OptionMessenger.showQuestionDialog(
								view,
								"Xác nhận xóa tài khoản "
										+ view.getUserNameSelected(),
								"Cảnh báo", OptionMessenger.QUESTION_MESSAGE) == OptionMessenger.OK_OPTION)
							delAccount();
				}
			} else {
				OptionMessenger.showMessageDialog(view,
						"Chọn tài khoản cần xóa", "Thông báo",
						OptionMessenger.QUESTION_MESSAGE);
			}
			break;
		case UICommand.SAVE_CMD:
			try {
				update();
			} catch (NullPointerException nullPointer) {
				OptionMessenger.showMessageDialog(
						OptionMessenger.windowForComponent(view),
						"Lỗi chưa xác định... Vui lòng liên hệ nhà phát triển để khắc phục\n"
								+ nullPointer.getMessage(), "Lỗi",
						OptionMessenger.ERROR_MESSAGE);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			break;
		case UICommand.REFRESH_CMD:
			view.clearSelectionTable();
			ActionListener action = new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {
						e1.printStackTrace();
					}
					tableModel.loadData(null);
				}
			};
			BusyDialog.showBusyDialog(OptionMessenger.windowForComponent(view),
					"Tải lại dữ liệu", action, null);
			break;
		case UICommand.CELL_CHECKBOX_CMD:
			if (view.checkUserName("admin", "guess")) {
				checkBox.setSelected(false);
				OptionMessenger
						.showMessageDialog(
								OptionMessenger.windowForComponent(view),
								"Đây là tài khoản hệ thống không thể thực hiện thao tác này",
								"Thông báo", OptionMessenger.WARNING_MESSAGE);
			} else {
				Account tmp = view.getAccountSelected();
				String query = "UPDATE account SET account.lock=? WHERE id=?";
				try {
					connect = Database.connect();
					PreparedStatement pre = connect.prepareStatement(query);
					pre.setBoolean(1, checkBox.isSelected());
					pre.setInt(2, tmp.getId());
					pre.executeUpdate();
				} catch (ClassNotFoundException e1) {
					e1.printStackTrace();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			break;
		case "exit": // used by cancel button
			view.exit();
			break;
		case "name":
		case "Author":
		case "lastLogin":
		case "exe":
		case "power":
			view.setEditable(cmd); // search field
			break;
		case "search":
			search();
			break;
		case "schFid":
			view.setTextName();
			break;
		}
	}

	// TODO update information the account
	private void update() throws NullPointerException, ClassNotFoundException,
			SQLException {
		if (view.checkUserName(0)) {
			// account may be null
			Account account = tableModel.getAccountAtRow(view
					.getSelectedRealRow());
			Account tmp = view.getAccountEdit();
			if (view.isEmptyPassField() && account.equals(tmp)) {
				OptionMessenger.showMessageDialog(view,
						"Không có gì cần thay đổi", "Thông báo",
						OptionMessenger.INFORMATION_MESSAGE);
				return;
			} else if (!view.isEmptyPassField()) {
				// edit name or pass or both
				if (view.checkPass(0) && view.checkReenter()) {
					update(account, true);
				} else {
					OptionMessenger.showMessageDialog(view,
							"Mật khẩu không trùng khớp hoặc không hợp lệ",
							"Lỗi", OptionMessenger.INFORMATION_MESSAGE);
				}
			} else { // edit name
				update(account, false);
			}
		} else {
			OptionMessenger.showMessageDialog(view,
					"Tên tài khoản không hơp lệ", "Lỗi",
					OptionMessenger.ERROR_MESSAGE);
		}
	}

	private void update(Account account, boolean newPass) {
		try {
			int ansquer = OptionMessenger.showQuestionDialog(
					view,
					"Bạn có chắc muốn thay đổi thông tin tài khoản "
							+ account.getName() + "?", "Xác nhận",
					OptionMessenger.QUESTION_MESSAGE);
			if (ansquer != OptionMessenger.OK_OPTION)
				return;
			connect = Database.connect();
			preStm = connect
					.prepareStatement("UPDATE account SET name=?,author=?,exe=?,password=? WHERE id=?");
			Account edit = view.getAccountUpdate(account, newPass);
			preStm.setString(1, edit.getName());
			preStm.setString(2, edit.getAuthor());
			preStm.setString(3, edit.getPower());
			preStm.setString(4, edit.getPass());
			preStm.setInt(5, edit.getId());

			preStm.executeUpdate();
			view.exit();
			tableModel.loadData(null);
			OptionMessenger.showMessageDialog(view, "Đã cập nhật thông tin",
					"Thông báo", OptionMessenger.INFORMATION_MESSAGE);
		} catch (ClassNotFoundException e) {
			e.printStackTrace(IOFile.getInstance());
		} catch (SQLException e) {
			e.printStackTrace(IOFile.getInstance());
			OptionMessenger.showMessageDialog(
					OptionMessenger.windowForComponent(view),
					"Lỗi trong khi kết nối dữ liệu", "Lỗi",
					OptionMessenger.ERROR_MESSAGE);
		}
	}

	private boolean isLoggin() {
		Account currentAccount = MainFrame.account;
		Account selected = view.getAccountSelected();
		if (currentAccount != null && selected != null) {
			if (selected.getId() == currentAccount.getId()) {
				OptionMessenger
						.showMessageDialog(
								view,
								"Tài khoản đang đăng nhập không thể thực hiện thao tác này",
								"Thông báo", OptionMessenger.WARNING_MESSAGE);
				return true;
			}
		}
		return false;
	}

	private boolean isUser() {
		Account account = MainFrame.account;
		String power = account.getPower();
		if (power.equalsIgnoreCase("user")) {
			OptionMessenger.showMessageDialog(view,
					"Tài khoản của bạn không đủ quyền hạn", "Cảnh báo",
					OptionMessenger.WARNING_MESSAGE);
			return true;
		}
		return false;
	}

	private boolean isValid() {
		return !isUser() && !isLoggin();
	}

	@Override
	public void focusGained(FocusEvent e) {
		((JTextField) e.getSource()).selectAll();
	}

	@Override
	public void focusLost(FocusEvent e) {

	}

	public void search() {
		String sql = "SELECT * FROM account WHERE ";
		if (view.isSelectedTable()) { // check query
			sql = sql.concat(view.createSQL());
		} else { // search field
			sql = sql.concat("name LIKE '%" + view.getSearchText() + "%'");
		}
		tableModel.loadData(sql);
	}

	@Override
	public void keyTyped(KeyEvent e) {

	}

	@Override
	public void keyPressed(KeyEvent e) {

	}

	@Override
	public void keyReleased(KeyEvent e) {
		String tmp = ((JTextField) e.getSource()).getName();
		if (tmp.isEmpty())
			return;
		switch (tmp) {
		case "user":
			view.checkUserName(e.getKeyCode());
			break;
		case "author":
			view.checkAuthor(e.getKeyCode());
			break;
		case "pass":
			view.checkPass(e.getKeyCode());
			break;
		case "repass":
			view.checkReenter();
			if (e.getKeyCode() == KeyEvent.VK_ENTER)
				view.getBtnAdd().doClick();
			break;
		}
	}

	// TODO add account to system
	public void addAccount() {
		if (view.checkUserName(0) && view.checkPass(0) && view.checkReenter()) {
			try {
				connect = model.Database.connect();

				// add new account
				PreparedStatement preStm = connect
						.prepareStatement("INSERT INTO account(name,author,password,exe) VALUES(?,?,'',?)");
				String[] query = view.getQueryAdd();
				for (int i = 0; i < query.length - 1; i++) {
					preStm.setString(i + 1, query[i]);
				}
				preStm.execute();

				// set password encryption id
				preStm = connect
						.prepareStatement("SELECT id FROM account WHERE name=?");
				preStm.setString(1, query[0]);
				ResultSet rs = preStm.executeQuery();
				if (rs.next()) {
					int id = rs.getInt("id");
					String pass = Encryption.encrypt(id
							+ query[query.length - 1]);
					preStm.executeUpdate("UPDATE account SET password='" + pass
							+ "' WHERE id=" + id);
				}

				tableModel.loadData(null);
				view.clearAddPanel();
				OptionMessenger.showMessageDialog(view,
						"Thêm tài khoản thành công", null,
						OptionMessenger.INFORMATION_MESSAGE);
			} catch (SQLException e) {
				e.printStackTrace(IOFile.getInstance());
				OptionMessenger.showMessageDialog(view,
						"Lỗi truy xuất cơ sở sữ liệu\n" + e.getMessage(),
						"Lỗi", OptionMessenger.ERROR_MESSAGE);
			} catch (ClassNotFoundException e) {
				e.printStackTrace(IOFile.getInstance());
			}
		} else {
			OptionMessenger
					.showMessageDialog(
							view,
							"Thông tin tài khoản hoặc mật khẩu không hợp lệ\nVui lòng xem lại các ràng buộc!",
							"Lỗi", OptionMessenger.ERROR_MESSAGE);
		}
	}

	// TODO remove account from system
	public void delAccount() {
		try {
			connect = model.Database.connect();

			preStm = connect
					.prepareStatement("DELETE FROM account WHERE name = ?");
			preStm.setString(1, view.getUserNameSelected());

			preStm.execute();
			tableModel.loadData(null);
		} catch (SQLException e) {
			e.printStackTrace(IOFile.getInstance());
		} catch (ClassNotFoundException e) {
			e.printStackTrace(IOFile.getInstance());
		}

	}

	@Override
	public void mouseClicked(MouseEvent e) {

	}

	@Override
	public void mousePressed(MouseEvent e) {
		view.showAdvancedFind();
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		view.showPopupMenu(e);
	}

	@Override
	public void mouseEntered(MouseEvent e) {

	}

	@Override
	public void mouseExited(MouseEvent e) {

	}

	public JPanel getView() {
		return this.view;
	}

	public void setCheckBoxEditor(JCheckBox checkbox) {
		this.checkBox = checkbox;
	}

}